package gcontext

import (
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"time"

	jsoniter "github.com/json-iterator/go"
)

// 二次封装gin的json返回方法
func (geCtx *GEContext) JSON(code int, obj interface{}) {
	geCtx.Gin.JSON(code, obj)
}

func (geCtx *GEContext) JSON_ECHO(obj interface{}) {
	geCtx.Gin.JSON(http.StatusOK, obj)
}

// 二次封装gin的string返回方法
func (geCtx *GEContext) String(code int, format string, values ...interface{}) {
	geCtx.Gin.String(code, format, values...)
}

func (geCtx *GEContext) EventStream(msg string) {
	geCtx.Gin.Writer.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
	geCtx.Gin.Writer.Header().Set("Cache-Control", "no-cache")
	geCtx.Gin.Writer.Header().Set("Connection", "keep-alive")
	// 禁用nginx缓存,防止nginx会缓存数据导致数据流是一段一段的
	geCtx.Gin.Writer.Header().Set("X-Accel-Buffering", "no")

	w := geCtx.Gin.Writer
	flusher, _ := w.(http.Flusher)
	flusher.Flush()

	for _, v := range msg {
		fmt.Fprintf(w, "%s", string(v))
		flusher.Flush()
		time.Sleep(10 * time.Millisecond)
	}
}

func (geCtx *GEContext) EventStreamV2(msgChan chan string) (content string) {
	geCtx.Gin.Writer.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
	geCtx.Gin.Writer.Header().Set("Cache-Control", "no-cache")
	geCtx.Gin.Writer.Header().Set("Connection", "keep-alive")
	// 禁用nginx缓存,防止nginx会缓存数据导致数据流是一段一段的
	geCtx.Gin.Writer.Header().Set("X-Accel-Buffering", "no")
	w := geCtx.Gin.Writer
	// wg := &sync.WaitGroup{}
	// wg.Add(1)
	// go func(c chan string, wg *sync.WaitGroup, w gin.ResponseWriter) {
	// 	defer wg.Done()
	flusher, _ := w.(http.Flusher)
	flusher.Flush()
	for m := range msgChan {
		fmt.Fprintf(w, "%s", m)
		content += m
		flusher.Flush()
	}
	// }(msgChan, wg, w)
	// wg.Wait()
	return
}

// 二次封装gin的取参方法, 会依次从POST, GET, URI 取参
// Deprecated: As of v0.1.43, this function simply calls [ctx.ParamAny].
func (geCtx *GEContext) AnyParam(key string) (value string) {
	return geCtx.ParamAny(key)
}

func (geCtx *GEContext) ParamAny(key string) (value string) {
	if value = geCtx.Gin.PostForm(key); len(value) != 0 {
		return
	}
	if value = geCtx.Gin.Query(key); len(value) != 0 {
		return
	}
	if value = geCtx.Gin.Param(key); len(key) != 0 {
		return
	}
	return
}

// 二次封装gin的取参方法, 支持传入默认值 取不到会返回默认值
func (geCtx *GEContext) DefaultAnyParam(key string, defaultValue string) (value string) {
	if value = geCtx.AnyParam(key); len(value) != 0 {
		return
	}
	return defaultValue
}

func (geCtx *GEContext) ParamInt(key string) (value int, err error) {
	value, err = strconv.Atoi(geCtx.AnyParam(key))
	return
}

func (geCtx *GEContext) ParamInt64(key string) (value int64, err error) {
	value, err = strconv.ParseInt(geCtx.AnyParam(key), 10, 64)
	return
}

func (geCtx *GEContext) ParamBool(key string) (value bool, err error) {
	value, err = strconv.ParseBool(geCtx.AnyParam(key))
	return
}

func (geCtx *GEContext) ParamArrayInt(key string) (vals []int, err error) {
	value := geCtx.Gin.PostFormArray(key)
	if len(value) == 0 {
		value = geCtx.Gin.QueryArray(key)
	}
	if len(value) > 0 {
		for _, v := range value {
			tmp, err := strconv.Atoi(v)
			if err == nil {
				vals = append(vals, tmp)
			}
		}
	}
	return
}

func (geCtx *GEContext) ParamArrayInt64(key string) (vals []int64, err error) {
	value := geCtx.Gin.PostFormArray(key)
	if len(value) == 0 {
		value = geCtx.Gin.QueryArray(key)
	}
	if len(value) > 0 {
		for _, v := range value {
			tmp, err := strconv.ParseInt(v, 10, 64)
			if err == nil {
				vals = append(vals, tmp)
			}
		}
	}
	return
}

func (geCtx *GEContext) ParamIntDefault(key string, def int) (value int, err error) {
	value, err = strconv.Atoi(geCtx.AnyParam(key))
	if err != nil {
		value = def
	}
	return
}

func (geCtx *GEContext) ParamInt64Default(key string, def int64) (value int64, err error) {
	value, err = strconv.ParseInt(geCtx.AnyParam(key), 10, 64)
	if err != nil {
		value = def
	}
	return
}

func (geCtx *GEContext) ParamBoolDefault(key string, def bool) (value bool, err error) {
	value, err = strconv.ParseBool(geCtx.AnyParam(key))
	if err != nil {
		value = def
	}
	return
}

func (geCtx *GEContext) GetLoginID() (userID int64, err error) {
	userID, ok := geCtx.Value("loginUserId").(int64)
	if !ok {
		err = errors.New("token error")
		return
	}
	return
}

func (geCtx *GEContext) GetLoginExtends() (extends string, err error) {
	extends, ok := geCtx.Value("loginExtends").(string)
	if !ok {
		err = errors.New("token error")
		return
	}
	return
}

func (geCtx *GEContext) GetTokenExtends(result interface{}) (err error) {
	exts, err := geCtx.GetLoginExtends()
	if err != nil {
		return
	}
	return jsoniter.UnmarshalFromString(exts, result)
}

func (geCtx *GEContext) ParamStringArray(key, sep string) []string {
	val := geCtx.AnyParam(key)
	return strings.Split(val, sep)
}

func (geCtx *GEContext) ParamJson(key string, result interface{}) (err error) {
	val := geCtx.AnyParam(key)
	return jsoniter.UnmarshalFromString(val, &result)
}
